/** Called automatically by JsDoc Toolkit. */
function publish(symbolSet) {
	publish.conf = {  // trailing slash expected for dirs
		outDir:      JSDOC.opt.d || SYS.pwd+"../out/jsdoc/",
		templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/gcodeWiki/",
		labels: ['Documentation'],
		srcDir: "http://code.google.com/p/av-jslib/source/browse/trunk/"
	};

	publish.labelList = "#labels " + publish.conf.labels.join(',');
	
	// create the folders and subfolders to hold the output
	IO.mkPath((publish.conf.outDir).split("/"));
		
	// used to allow Link to check the details of things being linked to
	Link.symbolSet = symbolSet;
	Link.base = "";

	// create the required templates
	try
	{
		var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
		var classIndex = new JSDOC.JsPlate(publish.conf.templatesDir+"Documentation.tmpl");
	}
	catch(e)
	{
		print("Couldn't create the required templates: "+e);
		quit();
	}
	
	// some ustility filters
	function hasNoParent($) {return ($.memberOf == "")}
	function isaFile($) {return ($.is("FILE"))}
	function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)}
	
	// get an array version of the symbolset, useful for filtering
	var symbols = symbolSet.toArray();
	
 	// get a list of all the classes in the symbolset
 	var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
	
	// create a filemap in which outfiles must be to be named uniquely, ignoring case
	if (JSDOC.opt.u) {
		var filemapCounts = {};
		Link.filemap = {};
		for (var i = 0, l = classes.length; i < l; i++) {
			var lcAlias = classes[i].alias.replace(/^_+|_+$|\./ig, ''),
			lcKey = lcAlias.toLowerCase();
			
			if (!filemapCounts[lcKey]) filemapCounts[lcKey] = 1;
			else filemapCounts[lcKey]++;
			
			Link.filemap[classes[i].alias] = 
				(filemapCounts[lcKey] > 1)?
				lcAlias+"_"+filemapCounts[lcKey] : lcAlias;
		}
	}
	var output, documentedClasses = [];

	// create each of the class pages
	for (var i = 0, l = classes.length; i < l; i++) {
		var symbol = classes[i];
		
		symbol.events = symbol.getEvents();   // 1 order matters
		symbol.methods = symbol.getMethods(); // 2
		
		if (symbol.properties.length || symbol.events.length || symbol.methods.length)
		{
			documentedClasses.push(classes[i]);
			output = "";
			output = classTemplate.process(symbol);
			
			IO.saveFile(publish.conf.outDir, ((JSDOC.opt.u) ? Link.filemap[symbol.alias] : symbol.alias) + ".wiki", output);
		}
	}
	
	// create a class index, displayed in the left-hand column of every class page
	output = publish.labelList + ",Featured\n" + classIndex.process(documentedClasses);
	IO.saveFile(publish.conf.outDir, "Documentation.wiki", output);
	
	classesindexTemplate = classesIndex = classes = null;
}


/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */
function summarize(desc) {
	if (typeof desc != "undefined")
		return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc;
}

/** Make a symbol sorter by some attribute. */
function makeSortby(attribute) {
	return function(a, b) {
		if (a[attribute] != undefined && b[attribute] != undefined) {
			a = a[attribute].toLowerCase();
			b = b[attribute].toLowerCase();
			if (a < b) return -1;
			if (a > b) return 1;
			return 0;
		}
	}
}

/** Pull in the contents of an external file at the given path. */
function include(path) {
	var path = publish.conf.templatesDir+path;
	return IO.readFile(path);
}

/** Build output for displaying function parameters. */
function makeSignature(params) {
	if (!params) return "()";
	var signature = "("
	+
	params.filter(
		function($) {
			return $.name.indexOf(".") == -1; // don't show config params in signature
		}
	).map(
		function($) {
			return $.name;
		}
	).join(", ")
	+
	")";
	return signature;
}

/** Find symbol {@link ...} strings in text and turn into html links */
function resolveLinks(str, from) {
	str = str.replace(/\{@link ([^} ]+) ?\}/gi,
		function(match, symbolName) {
			return symbolName;//new Link().toSymbol(symbolName);
		}
	);
	return str;
}
